# _*_ encoding:utf-8 _*_
import sys
sys.path.append("..")
import trafficindex.beijing_index
import optparse
import logging
import traci
try:
    import xml.etree.cElementTree as ET
except ImportError:
    import xml.etree.ElementTree as ET


def load_vehicles(filename):
    vehicles = {}
    depart_table = {}
    tree = ET.ElementTree(file=filename)
    for child in tree.getroot():
        if child.tag == 'vehicle':
            attrib = {}
            depart = int(float(child.attrib['depart']))
            attrib.setdefault('depart', depart)
            attrib.setdefault('id', child.attrib['id'])
            route = child[0].attrib['edges'].split(' ')
            attrib.setdefault('route', route)
            vehicles.setdefault(child.attrib['id'], attrib)
            depart_table.setdefault(depart, {})
            depart_table[depart].setdefault(child.attrib['id'], 1)

    return vehicles, depart_table


def test_load_vehicles():
    filename = "../../data/1101/11011607-t.rou.xml"
    vehicles, depart_table = load_vehicles(filename)
    print len(vehicles)
    sum = 0
    for depart in depart_table:
        sum += len(depart_table[depart])
    print sum


def load_main_road(filename):
    edges = {}

    tree = ET.ElementTree(file=filename)
    for child in tree.getroot():
        if child.tag == 'edge':
            attrib = child.attrib
            attrib.setdefault('speed', float(child[0].attrib['speed']))
            attrib.setdefault('length', float(child[0].attrib['length']))
            edges.setdefault(child.attrib['id'], attrib)
    return edges


def test_load_main_road():
    filename = "../../data/1101/hangzhou_main_road.net.xml"
    edges = load_main_road(filename)
    print len(edges)


def get_options(args=None):
    optparser = optparse.OptionParser()
    optparser.add_option('-n', '--net-file', dest='net_file', help=" the city road net file")
    optparser.add_option('-r', '--rou-file', dest='rou_file', help=" the route file")
    optparser.add_option('-o', '--output', dest='gps_file', help='output gps file')
    optparser.add_option('-v', '--velocity', dest='velocity', help="Instantaneous speed of edges")
    optparser.add_option("-p", '--remote-port', dest='port', type='int', help="the remote server port")
    optparser.add_option("-s", "--host", dest='host', help='the remote server ip')
    (options, args) = optparser.parse_args(args=args)

    # if not options.net_file or not options.rou_file or not options.gps_file or not options.port or not options.host:
    #     optparser.print_help()
    #     exit(0)
    options.net_file = "../../data/1101/hangzhou_main_road.net.xml"
    options.rou_file = "../../data/1101/11011607.rou.xml"
    options.gps_file = "../../data/1101/11011607-s-11-6-30.gps.csv"
    options.port = 9999
    options.host = "10.214.143.88"
    return options


def main(options=None):
    log_file = "../../data/1101/controller-30.logs"
    logging.basicConfig(level=logging.INFO, format="%(message)s", filename=log_file, filemode='a')
    trafficindex.beijing_index.IndexHandler.load_network(options.net_file)
    interval = 5
    index_output = "../../data/1101/index-calculate-11-6-30.res.csv"
    index_vfile = "../../data/1101/index-v-11-6-30.txt"
    index_handler = trafficindex.beijing_index.IndexHandler(interval * 60, index_output, index_vfile)

    #
    vehicles, depart_table = load_vehicles(options.rou_file)
    edges = load_main_road(options.net_file)

    traci.init(options.port, host=options.host)
    with open(options.gps_file, "a") as f:
        buf = []

        for step in range(21600, 36001):
            traci.simulationStep()
            if step % 1 == 0:
                print 'time {0}'.format(step)
                # check all edge's Instantaneous mean speed
                index = -1
                edges_speed = {}
                for edge_id in edges:
                    mean_speed = traci.edge.getLastStepMeanSpeed(edge_id)
                    edges_speed.setdefault(edge_id, mean_speed)
                    logging.info("time:{0},edge:{1},mean_speed:{2}".format(step, edge_id, mean_speed))
                # check all running vehicles
                vehicle_pool = traci.vehicle.getIDList()
                for v_id in vehicle_pool:
                    position = traci.vehicle.getPosition(v_id)
                    speed = traci.vehicle.getSpeed(v_id)
                    lane_id = traci.vehicle.getLaneID(v_id)
                    angle = traci.vehicle.getAngle(v_id)
                    pos = traci.vehicle.getLanePosition(v_id)
                    v_data = {}
                    v_data.setdefault('x', position[0])
                    v_data.setdefault('y', position[1])
                    v_data.setdefault('speed', speed)
                    v_data.setdefault('lane', lane_id)
                    v_data.setdefault('id', v_id)
                    v_data.setdefault('angle', angle)
                    v_data.setdefault('time', step)
                    v_data.setdefault('pos', pos)
                    tmp = index_handler.execute(v_data)
                    if tmp != -1:
                        index = tmp
                    line = "{0},{1},{2},{3},{4},{5},{6},{7}\n".format(v_id, step, position[0], position[1], speed, lane_id, pos, angle)
                    buf.append(line)
                if len(buf) > 500000:
                    f.writelines(buf)
                    del buf
                    buf = []
                if index != -1:
                    print index
                if index > 3:
                    #
                    for depart in range(1, 300):
                        mark_table = []
                        if depart + step not in depart_table:
                            continue
                        for v_id in depart_table[depart + step]:
                            for r_id in vehicles[v_id]['route']:
                                if edges_speed[r_id] < edges[r_id]['speed'] * 0.35:
                                    # depart later 10 min
                                    new_depart = vehicles[v_id]['depart'] + 600
                                    traci.vehicle.setDepart(v_id, new_depart)
                                    # mark the vehicle
                                    vehicles[v_id]['depart'] = new_depart
                                    depart_table.setdefault(new_depart, {})
                                    depart_table[new_depart].setdefault(v_id, 1)
                                    # depart_table.pop(v_id)
                                    mark_table.append(v_id)
                                    logging.info("time:{0},vehicle:{1},origin_depart:{2},new_depart:{3}".format(step, v_id, depart + step, new_depart))
                                    break
                        for v_id in mark_table:
                            if depart + step in depart_table:
                                depart_table[depart + step].pop(v_id)
                        del mark_table
                # then simulate
                del edges_speed
                del vehicle_pool

        if len(buf) > 0:
            f.writelines(buf)
            del buf

        traci.close()

# test_load_vehicles()
# test_load_main_road()
if __name__ == '__main__':
    main(get_options())
